package com.gsma.calendar.android.ui;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListAdapter;
import android.widget.SimpleCursorAdapter;
import android.widget.Spinner;
import android.widget.TextView;

import com.gsma.calendar.android.R;
import com.gsma.calendar.android.db.CalendarGSMAColumns;
import com.gsma.calendar.android.db.CalendarGsmaQuery;
import com.gsma.calendar.android.model.CalendarObject;
import com.gsma.calendar.android.model.Session;
import com.gsma.calendar.android.util.CalendarGsmaUtil;
import com.gsma.calendar.android.util.Config;
import com.gsma.calendar.android.util.MotionEventUtils;
import com.gsma.calendar.android.widget.ObservableScrollView;
import com.gsma.calendar.android.widget.SessionView;
import com.gsma.calendar.android.widget.SessionsLayout;
import com.gsma.calendar.android.widget.Workspace;

/**
 * Demonstrates expandable lists using a custom {@link ExpandableListAdapter}
 * from {@link BaseExpandableListAdapter}.
 */
public class AgendaDaysActivity extends Activity implements ObservableScrollView.OnScrollListener {


	private Workspace mWorkspace;
	private TextView mTitle;
	private int mTitleCurrentDayIndex = -1;
	private View mLeftIndicator;
	private View mRightIndicator;

	private static Time sTime = new Time();
	private static final long MON_START = parseTime("2012-02-27T00:00:00.000-00:00");
	private static final long TUE_START = parseTime("2012-02-28T00:00:00.000-00:00");
	private static final long WED_START = parseTime("2012-02-29T00:00:00.000-00:00");
	private static final long THU_START = parseTime("2012-03-01T00:00:00.000-00:00");

	private static final int TIME_FLAGS = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_ABBREV_WEEKDAY;

	private List<Session> sessionsList;
	private Spinner spinner;
	private Cursor cursorCalendar;

	/**
	 * A helper class containing object references related to a particular day
	 * in the schedule.
	 */
	private class Day {
		private ViewGroup rootView;
		private ObservableScrollView scrollView;
		// private View nowView;
		private SessionsLayout sessionsView;

		private String label = null;
		private long timeStart = -1;
		private long timeEnd = -1;
	}

	private List<Day> mDays = new ArrayList<Day>();

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.agenda_days);

		spinner = (Spinner) findViewById(R.id.spinner);
		String eventName = getIntent().getStringExtra(Config.EVENT);  
		// Temporary in UI

		String[] projection = new String[] { "_id", "name" };
		String selection = "selected=1";
		String path = "calendars";

		CalendarGsmaUtil calen = new CalendarGsmaUtil(AgendaDaysActivity.this);
		cursorCalendar = calen.getCalendarManagedCursor(projection, selection, path);

		SimpleCursorAdapter calendarAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_spinner_item, cursorCalendar, new String[] { "name" },
				new int[] { android.R.id.text1 });

		spinner.setAdapter(calendarAdapter);
		calendarAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

		Cursor cursor = managedQuery(CalendarObject.CONTENT_URI, CalendarGsmaQuery.PROJECTION, CalendarGSMAColumns.EVENT.getName() + "=?", new String [] {eventName}, null);
		sessionsList = new ArrayList<Session>();
		if (cursor != null && cursor.moveToFirst()) {
			do {
				Session session = new Session();
				session.setId(cursor.getInt(CalendarGsmaQuery._ID));
				session.setStartTimeUtc(cursor.getLong(CalendarGsmaQuery.START_TIME));
				session.setEndTimeUtc(cursor.getLong(CalendarGsmaQuery.END_TIME));
				session.setName(cursor.getString(CalendarGsmaQuery.SESSION));
				session.setDescription(cursor.getString(CalendarGsmaQuery.WHERE));
				sessionsList.add(session);
			} while (cursor.moveToNext());
		}

		// TODO
		// TimeZone.setDefault(Config.CONFERENCE_TIME_ZONE);
	}

	@Override
	public void onResume() {
		super.onResume();

		mWorkspace = (Workspace) findViewById(R.id.workspace);
		mTitle = (TextView) findViewById(R.id.agenda_day);

		mLeftIndicator = findViewById(R.id.indicator_left);
		mLeftIndicator.setOnTouchListener(new View.OnTouchListener() {
			public boolean onTouch(View view, MotionEvent motionEvent) {
				if ((motionEvent.getAction() & MotionEventUtils.ACTION_MASK) == MotionEvent.ACTION_DOWN) {
					mWorkspace.scrollLeft();
					return true;
				}
				return false;
			}
		});
		mLeftIndicator.setOnClickListener(new View.OnClickListener() {
			public void onClick(View view) {
				mWorkspace.scrollLeft();
			}
		});

		mRightIndicator = findViewById(R.id.indicator_right);
		mRightIndicator.setOnTouchListener(new View.OnTouchListener() {
			public boolean onTouch(View view, MotionEvent motionEvent) {
				if ((motionEvent.getAction() & MotionEventUtils.ACTION_MASK) == MotionEvent.ACTION_DOWN) {
					mWorkspace.scrollRight();
					return true;
				}
				return false;
			}
		});
		mRightIndicator.setOnClickListener(new View.OnClickListener() {
			public void onClick(View view) {
				mWorkspace.scrollRight();
			}
		});

		LayoutInflater inflater = getLayoutInflater();
		setupDay(inflater, MON_START);
		setupDay(inflater, TUE_START);
		setupDay(inflater, WED_START);
		setupDay(inflater, THU_START);

		updateWorkspaceHeader(0);
		mWorkspace.setOnScrollListener(new Workspace.OnScrollListener() {
			public void onScroll(float screenFraction) {
				updateWorkspaceHeader(Math.round(screenFraction));
			}
		}, true);

		setupSessions();

	}

	private void setupSessions() {

		List<Session> sessions = new ArrayList<Session>();
		for (Session session : sessionsList) {
			sessions.add(session);
		}
		groupSessions(sessions);

	}

	/**
	 * 
	 */
	private void groupSessions(List<Session> input) {
		List<Set<Session>> sessions = new ArrayList<Set<Session>>();
		for (Day day : mDays) {
			day.sessionsView.removeAllSessions();
			for (int i = 0, c = input.size(); i < c; i++) {
				Session e1 = input.get(i);
				// Process sessions per day
				if (sameDay(day, e1)) {
					Set<Session> inner = new HashSet<Session>();
					inner.add(e1);
					for (int j = i + 1; j < c; j++) {
						Session e2 = input.get(j);
						// Match times overlaps
						if (e2.getStartTimeUtc() == e1.getStartTimeUtc() && e2.getEndTimeUtc() == e1.getEndTimeUtc()
								|| e2.getStartTimeUtc() >= e1.getStartTimeUtc() && e2.getStartTimeUtc() < e1.getEndTimeUtc()
								/* && e2.getEndTimeUtc()>=e1.getEndTimeUtc() */
								|| e2.getStartTimeUtc() < e1.getStartTimeUtc() && e2.getEndTimeUtc() >= e1.getStartTimeUtc()
								&& e2.getEndTimeUtc() < e2.getEndTimeUtc()) {
							inner.add(e2);
						}
					}
					sessions.add(inner);
				}
			}

			// Fill day
			for (Set<Session> inner : sessions) {
				Iterator<Session> iter = inner.iterator();
				int columns = inner.size();
				int counter = 0;
				// Log.d(Config.LOG_TAG, "===");
				while (iter.hasNext()) {
					Session session = iter.next();

					final boolean isBreak = TextUtils.isEmpty(session.getDescription());
					final SessionView sessionView = new SessionView(this, session.getId(), session.getName(), session.getStartTimeUtc(),
							session.getEndTimeUtc(), false, counter++, columns, isBreak);
					sessionView.setOnClickListener(new OnClickListener() {
						@Override
						public void onClick(View v) {

							long calendarId = spinner.getSelectedItemId();
							Intent intent = new Intent(AgendaDaysActivity.this, SessionDetailActivity.class);
							intent.putExtra(Config.EVENT_ID, sessionView.getSessionId());
							intent.putExtra(Config.CALENDAR_ID, calendarId);
							startActivity(intent);
						}
					});
					day.sessionsView.addSession(sessionView, columns - counter);
				}
			}
			sessions.clear();
		}
	}

	private boolean sameDay(Day day, Session session) {
		boolean ret = false;
		if (session.getStartTimeUtc() >= day.timeStart && session.getEndTimeUtc() <= day.timeEnd) {
			ret = true;
		}
		return ret;
	}

	public void updateWorkspaceHeader(int dayIndex) {
		if (mTitleCurrentDayIndex == dayIndex) {
			return;
		}

		mTitleCurrentDayIndex = dayIndex;
		Day day = mDays.get(dayIndex);
		mTitle.setText(day.label);

		mLeftIndicator.setVisibility((dayIndex != 0) ? View.VISIBLE : View.INVISIBLE);
		mRightIndicator.setVisibility((dayIndex < mDays.size() - 1) ? View.VISIBLE : View.INVISIBLE);
	}

	private void setupDay(LayoutInflater inflater, long startMillis) {
		Day day = new Day();

		// Setup data
		day.timeStart = startMillis;
		day.timeEnd = startMillis + DateUtils.DAY_IN_MILLIS;

		// Setup views
		day.rootView = (ViewGroup) inflater.inflate(R.layout.sessions_content, null);

		day.scrollView = (ObservableScrollView) day.rootView.findViewById(R.id.sessions_scroll);
		day.scrollView.setOnScrollListener(this);

		day.sessionsView = (SessionsLayout) day.rootView.findViewById(R.id.sessions);
		// day.nowView = day.rootView.findViewById(R.id.sessions_now);

		day.sessionsView.setDrawingCacheEnabled(true);
		day.sessionsView.setAlwaysDrawnWithCacheEnabled(true);

		day.label = DateUtils.formatDateTime(this, startMillis, TIME_FLAGS);

		mWorkspace.addView(day.rootView);
		mDays.add(day);
	}

	public void onScrollChanged(ObservableScrollView view) {
		// Keep each day view at the same vertical scroll offset.
		try {
			final int scrollY = view.getScrollY();
			for (Day day : mDays) {
				if (day.scrollView != view) {
					day.scrollView.scrollTo(0, scrollY);
				}
			}
		} catch (Exception e) {
			Log.e(Config.LOG_TAG, e.toString());
		}
	}

	/**
	 * Parse the given string as a RFC 3339 timestamp, returning the value as
	 * milliseconds since the epoch.
	 */
	public static long parseTime(String time) {
		sTime.parse3339(time);
		return sTime.toMillis(false);
	}

}
